package top.lixunda.ecommerce.server.business;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.support.SFunction;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import org.springframework.beans.factory.annotation.Autowired;
import top.lixunda.ecommerce.server.business.api.entity.dto.PageConvertWrapperDTO;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.function.Function;

/**
 * 封装MyBatisPlus框架的Service层
 *
 * @author Xumda
 * @version time:2019/11/26 14:18
 */
@SuppressWarnings({"Duplicates", "WeakerAccess", "unused"})
public class BaseConvertServiceImpl<
        N extends BaseMapper<T>, T,
        S extends BaseServiceImpl<P, E>, P extends BaseMapper<E>, E
        , D> extends BaseServiceImpl<N, T> {

    @SuppressWarnings("SpringJavaAutowiredMembersInspection")
    @Autowired
    private S s;

    /**
     * 转换方法
     */
    private final Function<List<T>, List<D>> convertFunction;

    private final SFunction<E, ?> entityIdFun;

    private final SFunction<T, ?> detailIdFun;

    public BaseConvertServiceImpl(Function<List<T>, List<D>> convertFunction, SFunction<E, ?> entityIdFun, SFunction<T, ?> detailIdFun) {
        this.convertFunction = convertFunction;
        this.entityIdFun = entityIdFun;
        this.detailIdFun = detailIdFun;
    }

    /**
     * 基础表的service类
     *
     * @return 基础表的service对象
     */
    public BaseServiceImpl<P, E> getAtomicService() {
        return s;
    }

    /**
     * 级联分页
     *
     * @return 级联数据列表
     */
    private IPage<D> convertPage(Page<D> page, LambdaQueryWrapper<E> wrapper, LambdaQueryWrapper<T> queryWrapper,
                                 SFunction<E, ?> idFunction, SFunction<T, ?> detailIdFunction,
                                 Function<List<T>, List<D>> convertFun) {
        Page<E> tempPage = new Page<E>().setCurrent(page.getCurrent()).setSize(page.getSize());
        tempPage.setOrders(page.getOrders());
        IPage<E> goodOrderPage = getAtomicService().page(tempPage, wrapper == null ?
                new LambdaQueryWrapper<E>().select(idFunction) : wrapper.select(idFunction));
        page.setSize(goodOrderPage.getSize()).setTotal(goodOrderPage.getTotal()).setPages(goodOrderPage.getPages())
                .setCurrent(goodOrderPage.getCurrent());
        List<E> entityList = goodOrderPage.getRecords();
        if (entityList.size() == 0) {
            return page.setRecords(Collections.emptyList());
        }
        List<String> idList = new ArrayList<>(entityList.size());
        for (E e : entityList) {
            idList.add(String.valueOf(idFunction.apply(e)));
        }
        List<T> dtoList = getBaseMapper().selectList(queryWrapper == null ?
                new QueryWrapper<T>().lambda().in(detailIdFunction, idList) :
                queryWrapper.in(detailIdFunction, idList));
        page.setRecords(convertFun.apply(dtoList));
        return page;
    }

    /**
     * 根据id查询详细信息
     *
     * @param id 主键id
     * @return 详细数据
     */
    public D getConvertById(String id) {
        List<T> list = this.list(
                new QueryWrapper<T>().lambda().eq(detailIdFun, id));
        if (list == null || list.size() == 0) {
            return null;
        }
        List<D> resultList = convertFunction.apply(list);
        return resultList.size() > 0 ? resultList.get(0) : null;
    }

    /**
     * 根据多个id查询详细数据列表
     *
     * @param idList 多个id列表
     * @return 详细数据列表
     */
    public List<D> listConvertByIds(List<String> idList) {
        List<T> list = this.list(new QueryWrapper<T>().lambda().in(detailIdFun, idList));
        if (list == null || list.size() == 0) {
            return Collections.emptyList();
        }
        return convertFunction.apply(list);
    }

    /**
     * 条件获取一个详细数据
     *
     * @param queryWrapper 查询条件
     * @return 转换数据
     */
    public D getOneConvert(LambdaQueryWrapper<T> queryWrapper) {
        List<T> list = this.list(queryWrapper);
        if (list == null || list.size() == 0) {
            return null;
        }
        List<D> resultList = convertFunction.apply(list);
        return resultList.size() > 0 ? resultList.get(0) : null;
    }

    /**
     * 添加查询转换数据列表
     *
     * @param queryWrapper 查询条件
     * @return 转换数据列表
     */
    public List<D> listConvert(LambdaQueryWrapper<T> queryWrapper) {
        List<T> list = this.list(queryWrapper);
        if (list == null || list.size() == 0) {
            return Collections.emptyList();
        }
        return convertFunction.apply(list);
    }

    /**
     * 查询所有转换数据
     *
     * @return 所有转换数据支持的列表
     */
    public List<D> listConvert() {
        return convertFunction.apply(this.list());
    }

    /**
     * 获取数量
     *
     * @param queryWrapper 查询条件
     * @return 数据的个数
     */
    public int countConvert(LambdaQueryWrapper<E> queryWrapper) {
        return getAtomicService().count(queryWrapper);
    }

    /**
     * 获取所有的数量
     *
     * @return 数量
     */
    public int countConvert() {
        return getAtomicService().count();
    }

    /**
     * 分页条件查询
     *
     * @param pageWrapper 分页查询条件
     * @return 分页数据
     */
    public IPage<D> pageConvert(PageConvertWrapperDTO<E, T, D> pageWrapper) {
        return convertPage(pageWrapper.getPage(), pageWrapper.getPageWrapper(),
                pageWrapper.getQueryWrapper(), entityIdFun, detailIdFun, convertFunction);
    }

    /**
     * 分页查询
     *
     * @param page 分页数据
     * @return 分页数据
     */
    public IPage<D> pageConvert(Page<D> page) {
        return convertPage(page, null, null, entityIdFun, detailIdFun, convertFunction);
    }

}
